package com.usefullc.crawler.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.usefullc.common.enums.YesNoEnum;
import com.usefullc.common.exception.BizException;
import com.usefullc.common.util.BeanUtils;
import com.usefullc.crawler.domain.Active;
import com.usefullc.crawler.domain.ActiveInstance;
import com.usefullc.crawler.domain.OutputTemplate;
import com.usefullc.crawler.enums.ActiveInstanceStatusEnum;
import com.usefullc.crawler.enums.ProcessStatusEnum;
import com.usefullc.crawler.enums.RequestTypeEnum;
import com.usefullc.crawler.enums.TaskSpeedEnum;
import com.usefullc.crawler.mapper.ActiveInstanceMapper;
import com.usefullc.crawler.query.ActiveInstanceQuery;
import com.usefullc.crawler.selenium.CrawlerWebDriver;
import com.usefullc.crawler.selenium.CrawlerWebDriverBuilder3;
import com.usefullc.crawler.selenium.CrawlerWebDriverParam;
import com.usefullc.crawler.task.TaskMessage;
import com.usefullc.crawler.task.TaskMessageHandler;
import com.usefullc.crawler.task.TaskMessageQueue;
import com.usefullc.crawler.vo.ActiveInstanceVo;
import com.usefullc.crawler.vo.OutputContext;
import com.usefullc.system.entity.Pager;
import com.usefullc.system.service.AbstractBizService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 爬虫活动实例服务类
 *
 * @author: 星空
 * @date: 2022-12-14
 */
@Service
public class ActiveInstanceService extends AbstractBizService<ActiveInstanceMapper, ActiveInstance, ActiveInstanceQuery> {

    @Autowired
    private ActiveMainInstanceService activeMainInstanceService;

    @Autowired
    private ActiveService activeService;

    @Autowired
    private TaskMessageQueue taskMessageQueue;

    @Autowired
    private OutputTemplateService outputTemplateService;
    @Autowired
    private CrawlerWebDriverBuilder3 crawlerWebDriverBuilder;


    @Override
    protected QueryWrapper<ActiveInstance> getQueryWrapper(ActiveInstanceQuery query) {
        QueryWrapper<ActiveInstance> queryWrapper = super.getQueryWrapper(query);
        return queryWrapper;
    }

    public Pager<ActiveInstanceVo> findVoByPage(ActiveInstanceQuery query) {
        query.setExcludeColumns("responseAnalyseBody,responseBody,errContent,responseRawHeader");
        Pager<ActiveInstance> page = this.findByPage(query);
        Pager<ActiveInstanceVo> newPage = new Pager<>(page);
        List<ActiveInstance> dataList = page.getDataList();
        List<ActiveInstanceVo> newDataList = new ArrayList<>();
        newPage.setDataList(newDataList);
        for (ActiveInstance activeInstance : dataList) {
            ActiveInstanceVo activeInstanceVo = BeanUtils.beanCopy(activeInstance, ActiveInstanceVo.class);
            newDataList.add(activeInstanceVo);
        }
        return newPage;
    }

    public List<ActiveInstance> findAllAnalyseDataList(ActiveInstanceQuery query){
        query.setExcludeColumns("responseBody,errContent,responseRawHeader");
//        query.setId(39542L);
        List<ActiveInstance> dataList = this.findAll(query);
        return dataList;
    }

    @Transactional
    public void activeRequestUpdate(ActiveInstance activeInstance) {
        int result = this.updateStatus(activeInstance.getId(), activeInstance.getStatus());
        if (result > 0) {
            this.save(activeInstance);
//            Long activeMainInstanceId = activeInstance.getActiveMainInstanceId();
//            boolean success = activeInstance.getStatus() == ProcessStatusEnum.SUCCESS.getCode();
//            activeMainInstanceService.updateByActiveInstanceRequest(activeMainInstanceId, success);
        } else {
            throw new BizException("active instance is not RUNNING status,activeInstanceId=" + activeInstance.getId());
        }
    }

    int updateTaskStatus(Long id, Integer taskStatus) {
        return this.getBaseMapper().updateTaskStatus(id, taskStatus);
    }

    int updateTaskStatusAndStatus(Long id, Integer taskStatus, Integer status) {
        return this.getBaseMapper().updateTaskStatusAndStatus(id, taskStatus, status);
    }

    int updateStatus(Long id, Integer status) {
        return this.getBaseMapper().updateStatus(id, status);
    }

    @Transactional
    public void end(Long activeInstanceId, Integer status) {
        ActiveInstance activeInstance = this.findById(activeInstanceId);
        activeInstance.setErrContent("手动操作");
        //先判断对应的客户端task中有没有失败的，如果有失败，则整个失败，否则成功 todo
        activeInstance.setStatus(status);
        long takeTime = System.currentTimeMillis() - activeInstance.getGmtModified().getTime();
        activeInstance.setTakeTime(takeTime);
        //任务结束，设置为0
        activeInstance.setTaskStatus(YesNoEnum.NO.getCode());
        //回写数据库
        this.activeRequestUpdate(activeInstance);
    }

    public void output(Long activeInstanceId, Long outputTemplateId) {
        ActiveInstance activeInstance = this.findById(activeInstanceId);
        OutputTemplate outputTemplate = outputTemplateService.findById(outputTemplateId);
        //获取webdriver
        CrawlerWebDriver crawlerWebDriver = crawlerWebDriverBuilder.buildFirefox(new CrawlerWebDriverParam());
        OutputContext outputContext = new OutputContext();
        outputContext.setIndex(1);
        outputTemplateService.outputSingle(outputContext,activeInstance, outputTemplate, crawlerWebDriver);
    }

    public boolean reRun(List<Long> activeInstanceIds){
        for (Long activeInstanceId : activeInstanceIds) {
            ActiveInstance activeInstance = this.findById(activeInstanceId);
            addToQueue(activeInstance);
        }
        return true;
    }


    public boolean addToQueue(ActiveInstance activeInstance){
        int result = this.updateTaskStatusAndStatus(activeInstance.getId(), YesNoEnum.YES.getCode(), ActiveInstanceStatusEnum.RUNNING.getCode());
        if(result < 0){
            return false;
        }
        //重新设置进入，不然那后面保存会覆盖
        activeInstance.setStatus(ActiveInstanceStatusEnum.RUNNING.getCode());
        activeInstance.setTaskStatus(YesNoEnum.YES.getCode());

        TaskMessage<Long> taskMessage = new TaskMessage<>();
        taskMessage.setData(activeInstance.getId());
        Active active = activeService.findById(activeInstance.getActiveId());
        taskMessage.setReqType(RequestTypeEnum.getByCode(active.getRequestType()).getValue());
//        taskMessage.setSpeed(TaskSpeedEnum.SLOW.getCode());
        taskMessage.setTaskId(activeInstance.getActiveProcessId());
        taskMessageQueue.addTaskMessage(taskMessage);

        //清空
        activeInstance.setResponseAnalyseBody("");
        activeInstance.setResponseBody("");
        activeInstance.setResponseRawHeader("");
        this.save(activeInstance);
        return true;
    }


}
